<?php

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 * Description of BContextObj
 *
 * @author I062261
 */
class BContextObj {

    const Scope_User = "user";
    const Scope_BlynApp = "appNode"; //blynApp under user
    const Scope_CurrentNode = "node";
    const Scope_CurrentUINode = "uiNode";
    const Scope_Space = "space";
    const Scope_App = "app";
    const Scope_Operation = "operation";
    const Scope_OperationFlow = "operationFlow";
    const Scope_ScreenFlow = "screenFlow";
    const Scope_Screen = "screen";
    const Scope_Blyn = "blynApp"; //variable for global app
    const VariableName_BlynApp = "appNode"; //appNode is application level of variable for user
    const VariableName_CurrentNode = "CurrentNode";
    const VariableName_CurrentUINode = "CurrentUINode";
    const VariableName_CurrentSpace = "CurrentSpace";
    const VariableName_CurrentApp = "CurrentApp"; //variable unser service app
    const VariableName_CurrentOperation = "CurrentOperation";
    const VariableName_CurrentOperationFlow = "CurrentOperationFlow";
    const VariableName_CurrentScreenFlow = "CurrentScreenFlow";
    const VariableName_CurrentScreen = "CurrentScreen";
    const Current_Id = "Id";
    const VariableName_Class = "Class";
    const V_AppMeta = "appMeta";
    const V_CurrentNodeId = "currentNodeId";
    const V_CurrentSpaceId = "currentSpaceId";
    const V_CurrentAppId = "currentAppId";
    const V_CurrentOperationId = "currentOperationId";
    const V_CurrentOperationFlowId = "currentOperationFlowId";
    const V_CurrentScreenId = "currentScreenId";
    const V_CurrentScreenFlowId = "currentScreenFlowId";
    const V_CurrentScreenName = "currentScreenName";
    const V_CurrentScreenFlowName = "currentScreenFlowName";
    const V_CurrentOperationFlowName = "currentOperationFlowName";

    //put your code here
    protected $userNode = array();
    protected $appNode = array();
    protected $appMeta = array(); //save global variable for all users
    protected $currentNode = array();
    protected $currentSpace = array();
    protected $currentApp = array();
    protected $currentOperation = array();
    protected $currentOperationFlow = array();
    protected $currentUINode = array();
    protected $currentScreenFlow = array();
    protected $currentScreen = array();

    public function __construct() {
        $this->load();
    }

    public function load() {
        //$this->userNode = $this->getContextVariableInDataStore($name, self::Scope_User);
        $this->appMeta = $this->getContextVariableInDataStore(self::V_AppMeta, self::Scope_Blyn);
        $this->appNode = $this->getContextVariableInDataStore(self::VariableName_BlynApp, self::Scope_User);
        $this->currentSpace = isset($this->appNode[self::VariableName_CurrentSpace]) ? $this->appNode[self::VariableName_CurrentSpace] : array();
        $this->currentApp = isset($this->currentSpace[self::VariableName_CurrentApp]) ? $this->currentSpace[self::VariableName_CurrentApp] : array();
        $this->currentOperationFlow = isset($this->currentApp[self::VariableName_CurrentOperationFlow]) ? $this->currentApp[self::VariableName_CurrentOperationFlow] : array();
        $this->currentOperation = isset($this->currentApp[self::VariableName_CurrentOperation]) ? $this->currentApp[self::VariableName_CurrentOperation] : array();
        $this->currentNode = isset($this->appNode[self::VariableName_CurrentNode]) ? $this->appNode[self::VariableName_CurrentNode] : array();
        $this->currentUINode = $this->currentNode;
        $this->currentScreen = isset($this->currentNode[self::VariableName_CurrentScreen]) ? $this->currentNode[self::VariableName_CurrentScreen] : array();
        $this->currentScreenFlow = isset($this->currentNode[self::VariableName_CurrentScreenFlow]) ? $this->currentNode[self::VariableName_CurrentScreenFlow] : array();
    }

    //structure of Context structure
    /**
     * 
     * user can contain a lot of Context variable, user's scope of variable match to session
     * one user can only contain one appNode, one appNode can only contain one currentNode or currentUINode
     * currentNode equal to currentUINode
     * currentNode can contain only one currentScreenFlow or only one current screen
     */
    public function addContextVariable($scope, $name, $value) {
        if ($scope == self::Scope_Blyn) {
            $this->appMeta[$name] = $value;
        }

        if ($scope == self::Scope_User) {
            $this->userNode[$name] = $value;
        }

        if ($scope == self::Scope_BlynApp) {
            $this->appNode[$name] = $value;
        }

        if ($scope == self::Scope_CurrentNode || $scope == self::Scope_CurrentUINode) {
            $this->currentNode[$name] = $value;
            $this->currentUINode = $this->currentNode;
        }
        if ($scope == self::Scope_Space) {
            $this->currentSpace[$name] = $value;
        }
        if ($scope == self::Scope_App) {
            $this->currentApp[$name] = $value;
        }
        if ($scope == self::Scope_Operation) {
            $this->currentOperation[$name] = $value;
        }
        if ($scope == self::Scope_OperationFlow) {
            $this->currentOperationFlow[$name] = $value;
        }

        if ($scope == self::Scope_Screen) {
            $this->currentScreen[$name] = $value;
        }
        if ($scope == self::Scope_ScreenFlow) {
            $this->currentScreenFlow[$name] = $value;
        }
    }

    public function getContextVariable($scope, $name) {

        //$currentUser = Blyn::app()->getCurrentUser();
        //return user's variable
        if ($scope == self::Scope_User && $name != self::VariableName_BlynApp) {
            //return $currentUser->getContextVariable($name);
            if (!isset($this->userNode[$name])) {
                return $this->getContextVariableInDataStore($name, self::Scope_User);
            }
            else
                return isset($this->userNode[$name]) ? $this->userNode[$name] : FALSE;
        } else if ($scope == self::Scope_Blyn) {
            //return global variable
            //if (empty($this->appMeta))
            //$this->appMeta = $this->getContextVariableInDataStore(self::V_AppMeta, self::Scope_Blyn);
            return isset($this->appMeta[$name]) ? $this->appMeta[$name] : FALSE;
        } else {
            //if (empty($this->appNode)) {
                //$this->appNode = $this->getContextVariableInDataStore(self::VariableName_BlynApp, self::Scope_User);
                //$this->appNode['retrieved'] = TRUE;
            //}

            if ($scope == self::Scope_BlynApp) {
                //equal to user variable belong to one login session
                return isset($this->appNode[$name]) ? $this->appNode[$name] : FALSE;
            }
            if ($scope == self::Scope_CurrentNode || $scope == self::Scope_CurrentUINode) {
                return isset($this->currentNode[$name]) ? $this->currentNode[$name] : FALSE;
            }
            if ($scope == self::Scope_Space) {
                return isset($this->currentSpace[$name]) ? $this->currentSpace[$name] : FALSE;
            }
            if ($scope == self::Scope_App) {
                return isset($this->currentApp[$name]) ? $this->currentApp[$name] : FALSE;
            }
            if ($scope == self::Scope_Operation) {
                return isset($this->currentOperation[$name]) ? $this->currentOperation[$name] : FALSE;
            }
            if ($scope == self::Scope_OperationFlow) {
                return isset($this->currentOperationFlow[$name]) ? $this->currentOperationFlow[$name] : FALSE;
            }
            if ($scope == self::Scope_Screen) {
                return isset($this->currentScreen[$name]) ? $this->currentScreen[$name] : FALSE;
            }
            if ($scope == self::Scope_ScreenFlow) {
                return isset($this->currentScreenFlow[$name]) ? $this->currentScreenFlow[$name] : FALSE;
            }
        }
    }

    public function resetContextVariable($scope, $name = NULL) {
        //the logic for reset user scope of variable is little different of other variable
        //user scope of variable will not be remove in user scope for unload of user scope of variable

        if ($scope == self::Scope_User) {
            if ($name == NULL) {
                foreach ($this->userNode as $key => $value) {
                    $this->userNode[$key] = array();
                }
            }
            if (isset($this->userNode[$name]))
                $this->userNode[$name] = array();
        }

        if ($scope == self::Scope_Blyn) {
            if ($name == NULL) {
                $this->appMeta = array();
            }
            if (isset($this->appMeta[$name]))
                $this->appMeta[$name] = NULL;
        }

        if ($scope == self::Scope_BlynApp) {
            if ($name == NULL) {
                //$this->appMeta = array();
                $this->appNode = array();
                $this->currentNode = array();
                $this->currentScreen = array();
                $this->currentScreenFlow = array();
                $this->currentUINode = array();
            }
            if (isset($this->appNode[$name]))
                $this->appNode[$name] = array();
        }

        if ($scope == self::Scope_CurrentNode || $scope == self::Scope_CurrentUINode) {
            if ($name == NULL) {
                $this->currentNode = array();
                $this->currentUINode = array();
                $this->currentScreenFlow = array();
                $this->currentScreen = array();
            }
            if (isset($this->currentNode[$name])) {
                $this->currentNode[$name] = array();
            }
            $this->currentUINode = $this->currentNode;
            $this->appNode['CurrentNode'] = $this->currentNode;
        }

        if ($scope == self::Scope_Screen) {
            if ($name == NULL) {
                $this->currentScreen = array();
            }
            if (isset($this->currentScreen[$name]))
                $this->currentScreen[$name] = array();
        }
        if ($scope == self::Scope_ScreenFlow) {
            if ($name == NULL) {
                $this->currentScreenFlow = array();
            }
            if (isset($this->currentScreenFlow[$name]))
                $this->currentScreenFlow[$name] = array();
        }
        if ($scope == self::Scope_Space) {
            if ($name == NULL) {
                $this->currentSpace = array();
            }
            if (isset($this->currentSpace[$name]))
                $this->currentSpace[$name] = array();
        }
        if ($scope == self::Scope_App) {
            if ($name == NULL) {
                $this->currentApp = array();
            }
            if (isset($this->currentApp[$name]))
                $this->currentApp[$name] = array();
        }
        if ($scope == self::Scope_OperationFlow) {
            if ($name == NULL) {
                $this->currentOperationFlow = array();
            }
            if (isset($this->currentOperationFlow[$name]))
                $this->currentOperationFlow[$name] = array();
        }
        if ($scope == self::Scope_Operation) {
            if ($name == NULL) {
                $this->currentOperation = array();
            }
            if (isset($this->currentOperation[$name]))
                $this->currentOperation[$name] = array();
        }

        /*
          if ($scope == self::Scope_BlynApp) {
          $this->deleteContextVariableInDataStore($name, self::Scope_BlynApp);
          } elseif ($scope == self::Scope_User) {
          $this->deleteContextVariableInDataStore($name, self::Scope_User);
          } else {
          $this->saveContextVariableInDataStore(self::VariableName_app, $this->appNode, self::Scope_User);
          }
         * 
         */
    }

    /**
     * this function save Context variable to database
     * @param type $scope
     * @param type $name
     */
    public function saveContextVariable() {

        //$currentUser = Blyn::app()->getCurrentUser();

        if ($this->currentScreen != NULL)
            $this->currentNode[self::VariableName_CurrentScreen] = $this->currentScreen;

        if ($this->currentScreenFlow != NULL)
            $this->currentNode[self::VariableName_CurrentScreenFlow] = $this->currentScreenFlow;

        if ($this->currentNode != NULL) {
            $this->appNode[self::VariableName_CurrentNode] = $this->currentNode;
            $this->currentUINode = $this->currentNode;
            //$this->appNode[self::VariableName_CurrentUINode] = $this->currentUINode;
        }

        if ($this->currentOperation != NULL)
            $this->currentApp[self::VariableName_CurrentOperation] = $this->currentOperation;

        if ($this->currentOperationFlow != NULL)
            $this->currentApp[self::VariableName_CurrentOperationFlow] = $this->currentOperationFlow;

        if ($this->currentApp != NULL)
            $this->currentSpace[self::VariableName_CurrentApp] = $this->currentApp;

        if ($this->currentSpace != NULL)
            $this->appNode[self::VariableName_CurrentSpace] = $this->currentSpace;

        if ($this->appNode != NULL)
            $this->userNode[self::VariableName_BlynApp] = $this->appNode;

        //$this->userNode[self::V_AppMeta] = $this->appMeta;
        //save appMeta
        if ($this->appMeta != NULL) {
            $value = serialize($this->appMeta);
            $this->saveContextVariableInDataStore(self::V_AppMeta, $value, self::Scope_Blyn);
        }

        if ($this->userNode != NULL) {
            foreach ($this->userNode as $name => $value) {
                if ($value != NULL) {
                    //$currentUser->addContextVariauserble($name, $value);
                    $this->saveContextVariableInDataStore($name, serialize($value), self::Scope_User);
                }
            }
        }
    }

    //this function will delete variables from database store
    public function deleteContextVariables($scope, $name = NULL) {

        //$currentUser = Blyn::app()->getCurrentUser();

        if ($scope == self::Scope_User) {
            if ($name == NULL) {
                foreach ($this->userNode as $name => $variable) {
                    //$currentUser->resetContextVariable($name);
                    $this->resetContextVariable(self::Scope_User, $name);
                }
            } else {
                //$currentUser->resetContextVariable($name);
                $this->resetContextVariable(self::Scope_User, $name);
            }
        } else {
            $this->resetContextVariable($scope, $name);
        }
        $this->saveContextVariable();
    }

    protected function getContextVariableInDataStore($name, $scope = null, $type = NULL) {

        if ($scope == self::Scope_User) {
            $userId = Blyn::app()->getCurrentUser()->getId();

            //if ($scope == NULL)
            $scope = 'u_' . $userId;
        }

        $mObj = BMContextVariable::model()->findByAttributes(array('scope' => $scope, 'name' => $name));

        if ($mObj != NULL) {
            $value = $mObj->value;
            if ($value != NULL) {
                $retValue = unserialize($value);
                return $retValue;
            }
        }

        return FALSE;
    }

    protected function saveContextVariableInDataStore($name, $value, $scope = NULL, $type = NULL) {

        if ($scope == self::Scope_User) {
            $userId = Blyn::app()->getCurrentUser()->getId();

            //if ($scope == NULL)
            $scope = 'u_' . $userId;
        }

        $mObj = BMContextVariable::model()->findByAttributes(array('scope' => $scope, 'name' => $name));

        if ($mObj == NULL) {
            $mObj = new BMContextVariable();
            $mObj->scope = $scope;
            $mObj->name = $name;
        }

        $mObj->value = $value;

        return $mObj->save();

        return FALSE;
    }

    protected function deleteContextVariableInDataStore($name = null, $scope = NULL, $scopeType = null) {

        if ($scope == self::Scope_User) {
            $userId = Blyn::app()->getCurrentUser()->getId();

            //if ($scope == NULL)
            $scope = 'u_' . $userId;
        }

        $mObj = BMContextVariable::model()->findByAttributes(array('scope' => $scope, 'name' => $name));

        if ($mObj != NULL) {
            return BMContextVariable::model()->deleteByPk($mObj->_id);
        }

        return FALSE;
    }

}

?>
